package com.ziyueyuwen.xiniao.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.ziyueyuwen.xiniao.service.*;
import com.ziyueyuwen.xiniao.bean.ZyClassLessonInfo;
import com.ziyueyuwen.xiniao.bean.ZyLessonMessageTask;
import com.ziyueyuwen.xiniao.bean.ZyUser;
import com.ziyueyuwen.xiniao.bean.message.LessonNode;
import com.ziyueyuwen.xiniao.dao.ZyClassLessonInfoMapper;
import com.ziyueyuwen.xiniao.dao.ZyLessonMessageTaskMapper;
import com.ziyueyuwen.xiniao.enums.MessageTypeEnum;
import com.ziyueyuwen.xiniao.util.DateUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import java.util.*;
import java.util.stream.Collectors;

import static com.ziyueyuwen.xiniao.enums.MessageTypeEnum.*;

/**
 * @author wancheng  on 2019/1/21.
 */
@Service
public class MessageTaskTemplateServiceImpl implements MessageTaskTemplateService {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    private final Integer TWO_DAY = 2 * 24;
    private final Integer TWENTY_HOUR = 20;

    @Autowired
    ZyLessonMessageTaskMapper zyLessonMessageTaskMapper;
    @Autowired
    ZyClassLessonInfoMapper zyClassLessonInfoMapper;
    @Autowired
    WxMessageService wxMessageService;
    @Autowired
    UserService userService;
    @Autowired
    MessageTaskService messageTaskService;
    @Autowired
    LessonUserService lessonUserService;
    @Autowired
    TransferStudentService transferStudentService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<ZyLessonMessageTask> getLinkedListTask(List<ZyClassLessonInfo> list) {
        logger.info("课节消息模板添加传参:list={}", JSONArray.toJSONString(list));
        //根据课节生成链表节点
        List<LessonNode> nodes = list.stream().map(this::setLessonNode).collect(Collectors.toList());
        //消息任务存储链表
        LinkedList<LessonNode> lessonNodes = new LinkedList<>();
        nodes.forEach(
                n -> {
                    LessonNode last = lessonNodes.peekLast();
                    if (last != null) {
                        n.setPrevious(last);
                        n.setHasPrevious(true);
                    }
                    lessonNodes.addLast(n);
                }
        );
        //转为array,方便查询
        List<LessonNode> arrayNodes = new ArrayList<>(lessonNodes);
        List<ZyLessonMessageTask> messageList = new ArrayList<>();
        //遍历循环,课前预习规则判断
        arrayNodes.forEach(
                n -> {
                    ZyLessonMessageTask preview = n.getPreview();
                    if (n.getHasPrevious()) {
                        //连续两个课节间隔如果小于2天
                        if (DateUtil.caleHour(n.getPrevious().getLesson().getEndTime(), n.getLesson().getBeginTime(), true) < TWO_DAY) {
                            preview.setSendTime(DateUtils.addHours(n.getLesson().getBeginTime(), -22));
                            n.setPreview(preview);
                        }
                    }
                    messageList.add(n.getPreview());
                    messageList.add(n.getOneHour());
                    messageList.add(n.getFifteenMinute());
                    messageList.add(n.getHomework());
                    messageList.add(n.getReplay());
                    messageList.add(n.getSummarize());
                    messageList.add(n.getUnCommit());
                    messageList.add(n.getExpansion());
                }
        );
        logger.info("生成的消息模板:messageList={}", JSONArray.toJSONString(messageList));
        if (!CollectionUtils.isEmpty(messageList)) {
            zyLessonMessageTaskMapper.insertBatch(messageList);
        }
        return messageList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertLessonTask(ZyClassLessonInfo lessonInfo) {
        LessonNode node = setLessonNode(lessonInfo);
        setPreviewTime(node, lessonInfo);
        List<ZyLessonMessageTask> tasks = new ArrayList<>();
        tasks.add(node.getPreview());
        tasks.add(node.getOneHour());
        tasks.add(node.getFifteenMinute());
        tasks.add(node.getReplay());
        tasks.add(node.getHomework());
        tasks.add(node.getSummarize());
        tasks.add(node.getExpansion());
        tasks.add(node.getUnCommit());
        zyLessonMessageTaskMapper.insertBatch(tasks);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertLessonTaskBatch(List<ZyClassLessonInfo> lessonInfos) {
        if (CollectionUtils.isNotEmpty(lessonInfos)){
            lessonInfos.forEach(this::insertLessonTask);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateLessonTime(Integer lessonId, Date beginTime, Date endTime) {
        ZyClassLessonInfo lesson = new ZyClassLessonInfo();
        lesson.setId(lessonId);
        lesson.setBeginTime(beginTime);
        lesson.setEndTime(endTime);
        LessonNode node = setLessonNode(lesson);
        setPreviewTime(node, lesson);
        List<ZyLessonMessageTask> tasks = new ArrayList<>();
        tasks.add(node.getPreview());
        tasks.add(node.getOneHour());
        tasks.add(node.getFifteenMinute());
        tasks.add(node.getReplay());
        tasks.add(node.getHomework());
        tasks.add(node.getSummarize());
        tasks.add(node.getExpansion());
        tasks.add(node.getUnCommit());
        tasks.forEach(
                t -> {
                    ZyLessonMessageTask param = new ZyLessonMessageTask();
                    param.setLessonId(lessonId);
                    param.setType(t.getType());
                    ZyLessonMessageTask ifExist = zyLessonMessageTaskMapper.selectOne(param);
                    if (ifExist == null) {
                        zyLessonMessageTaskMapper.insertSelective(t);
                    } else {
                        zyLessonMessageTaskMapper.updateSendTimeByLessonIdAndType(lessonId, t.getType(), t.getSendTime());
                    }

                }
        );
    }

    /**
     * 课前预习发送时间
     *
     * @param node
     * @param lessonInfo
     */
    private void setPreviewTime(LessonNode node, ZyClassLessonInfo lessonInfo) {
        ZyClassLessonInfo previous = zyClassLessonInfoMapper.getPreviousLesson(lessonInfo.getId());
        if (previous != null && DateUtil.caleHour(lessonInfo.getEndTime(), previous.getEndTime(), true) < TWO_DAY) {
            node.getPreview().setSendTime(DateUtils.addHours(lessonInfo.getBeginTime(), -22));
        }
    }

    @Override
    public List<ZyLessonMessageTask> getTask(Date before, Date end) {
        return zyLessonMessageTaskMapper.getByBetween(before, end);
    }

    @Override
    public void executeTask(List<ZyLessonMessageTask> tasks) {
        if (CollectionUtils.isEmpty(tasks)) {
            return;
        }
        Set<Integer> lessonIdSet = tasks.stream().map(ZyLessonMessageTask::getLessonId).collect(Collectors.toSet());
        Map<Integer, List<ZyUser>> classStudent = new HashMap<>(100);
        lessonIdSet.forEach(
                lessonId -> {
                    List<ZyUser> students = userService.getStudentsByLessonId(lessonId);
                    List<ZyUser> transferStudent = userService.getTransferStudent(lessonId);
                    students.addAll(transferStudent);
                    classStudent.put(lessonId, students);
                }
        );
        tasks.forEach(
                t -> {
                    Integer lessonId = t.getLessonId();
                    List<ZyUser> students = classStudent.get(lessonId);
                    students.forEach(
                            s -> {
                                try {
                                    String studentAccount = s.getUserAccount();
                                    switch (t.getType()) {
                                        case MESSAGE_LESSON_INFLATED:
                                            if (!messageTaskService.ifHasTask(lessonId, MESSAGE_LESSON_INFLATED)) {
                                                t.setIfNeedSend(false);
                                                break;
                                            }
                                            wxMessageService.sendClassRemindInflated(studentAccount, lessonId, t.getId());
                                            break;
                                        case MESSAGE_LESSON_BEFORE_ONE_HOUR:
                                            wxMessageService.sendLessonBeforeOneHour(studentAccount, lessonId, t.getId());
                                            break;
                                        case MESSAGE_LESSON_BEFORE_FIFTEEN_MINUTE:
                                            wxMessageService.sendLessonBeforeFifteenMinute(studentAccount, lessonId, t.getId());
                                            break;
                                        case MESSAGE_LESSON_URL_SUMMARIZE:
                                            if (!messageTaskService.ifHasTask(lessonId, MESSAGE_LESSON_URL_SUMMARIZE)) {
                                                t.setIfNeedSend(false);
                                                break;
                                            }
                                            wxMessageService.sendLessonSummarize(studentAccount, lessonId, t.getId());
                                            break;
                                        case MESSAGE_LESSON_HOMEWORK:
                                            if (!messageTaskService.ifHasTask(lessonId, MESSAGE_LESSON_HOMEWORK)) {
                                                t.setIfNeedSend(false);
                                                break;
                                            }
                                            wxMessageService.sendLessonHomework(studentAccount, lessonId, t.getId());
                                            break;
                                        case MESSAGE_LESSON_HOMEWORK_UN_COMMIT:
                                            if (!messageTaskService.ifHasTask(lessonId, MESSAGE_LESSON_HOMEWORK)) {
                                                t.setIfNeedSend(false);
                                                break;
                                            }
                                            wxMessageService.sendLessonHomeworkUnCommit(studentAccount, lessonId, t.getId());
                                            break;
                                        case MESSAGE_LESSON_EXPANSION:
                                            if (!messageTaskService.ifHasTask(lessonId, MESSAGE_LESSON_EXPANSION)) {
                                                t.setIfNeedSend(false);
                                                break;
                                            }
                                            wxMessageService.saveLessonExpansion(studentAccount, lessonId, t.getId());
                                            break;
                                        default:
                                            break;
                                    }
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            }
                    );
                    t.setIfExecute(true);
                    zyLessonMessageTaskMapper.updateByPrimaryKeySelective(t);
                }
        );

    }

    @Override
    public List<ZyLessonMessageTask> getLessonHasExecuteTask(Integer lessonId, Date date) {
        return zyLessonMessageTaskMapper.getTaskByLessonIdAndSendTimeBefore(lessonId,date);
    }

    private LessonNode setLessonNode(ZyClassLessonInfo lesson) {
        LessonNode lessonNode = new LessonNode();
        Date beginTime = lesson.getBeginTime();
        Date endTime = lesson.getEndTime();
        ZyLessonMessageTask preview = new ZyLessonMessageTask("课前预习", DateUtils.addDays(beginTime, -2), MessageTypeEnum.MESSAGE_LESSON_INFLATED, lesson.getId());
        ZyLessonMessageTask oneHour = new ZyLessonMessageTask("上课前1小时提醒", DateUtils.addHours(beginTime, -1), MessageTypeEnum.MESSAGE_LESSON_BEFORE_ONE_HOUR, lesson.getId());
        ZyLessonMessageTask fifteenMinute = new ZyLessonMessageTask("上课前15分钟提醒", DateUtils.addMinutes(beginTime, -15), MessageTypeEnum.MESSAGE_LESSON_BEFORE_FIFTEEN_MINUTE, lesson.getId());
        ZyLessonMessageTask homework = new ZyLessonMessageTask("下课10分钟推送作业", DateUtils.addMinutes(endTime, 10), MESSAGE_LESSON_HOMEWORK, lesson.getId());
        ZyLessonMessageTask summarize = new ZyLessonMessageTask("下课10分钟推送课程总结", DateUtils.addMinutes(endTime, 10), MESSAGE_LESSON_URL_SUMMARIZE, lesson.getId());
        ZyLessonMessageTask replay = new ZyLessonMessageTask("直播链接或回放", beginTime, MessageTypeEnum.MESSAGE_LESSON_URL_REPLAY, lesson.getId());
        ZyLessonMessageTask unCommit = new ZyLessonMessageTask("作业推送48小时后再次推送", DateUtils.addHours(endTime, 48), MessageTypeEnum.MESSAGE_LESSON_HOMEWORK_UN_COMMIT, lesson.getId());
        ZyLessonMessageTask expansion = new ZyLessonMessageTask("课后拓展", endTime, MESSAGE_LESSON_EXPANSION, lesson.getId());
        lessonNode.setLesson(lesson)
                .setPreview(preview)
                .setOneHour(oneHour)
                .setFifteenMinute(fifteenMinute)
                .setHomework(homework)
                .setSummarize(summarize)
                .setReplay(replay)
                .setUnCommit(unCommit)
                .setExpansion(expansion);
        return lessonNode;
    }
}
